home *** CD-ROM | disk | FTP | other *** search
- Subject: v23i076: Feed multiple printers from one BSD lpr queue
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 6dc6d13d 1ce5265b f8c0866b 0b0db86c
-
- Submitted-by: matt robinson <yakker@ucrmath.ucr.edu>
- Posting-number: Volume 23, Issue 76
- Archive-name: mlpd
-
- [ I have not tested this as I don't run LDP. --r$ ]
-
- This program (MLPD) is a little piece of code I wrote to use a single
- printer queue for a set of multiple printers. It's kind of wierd to
- set up, but once it is running, it should help out a lot.
-
- The program runs under a Sun OS environment. It has been tried out
- under 4.1 SunOS, and I had it tried out under a 4.3 BSD environment,
- thanks to the help of nash@ucselx.sdsu.edu (Thanks, Ron!) I hope that
- it works for you. Please send me all bug reports, special things that
- would make your life easier, etc., so on, so forth. If you do have any
- questions at all, please mail me to let me know about what you need.
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: COPYRIGHT Makefile README config.h daemon.c lock.c mlp.c
- # mlpd.8 pfile.c printcap.c printer.c
- # Wrapped by rsalz@litchi.bbn.com on Wed Dec 5 12:24:56 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive."'
- if test -f 'COPYRIGHT' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'COPYRIGHT'\"
- else
- echo shar: Extracting \"'COPYRIGHT'\" \(1054 characters\)
- sed "s/^X//" >'COPYRIGHT' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1990 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by the University of California, Riverside.
- X *
- X * NOTE : That's Riverside. Not Berkeley, not Santa Cruz, not even
- X * Irvine. Riverside. Ri - ver - side.
- X *
- X * The name of the University may not be used to endorse or promote
- X * products derived from this software without specific prior written
- X * permission.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * MLPD -- Multiple Line Printer Daemon (Version 1.3)
- X * SCCS keywords: @(#)COPYRIGHT 1.3 12/1/90
- X */
- X
- END_OF_FILE
- if test 1054 -ne `wc -c <'COPYRIGHT'`; then
- echo shar: \"'COPYRIGHT'\" unpacked with wrong size!
- fi
- # end of 'COPYRIGHT'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(1775 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X#
- X# Copyright (c) 1990 Regents of the University of California.
- X# All rights reserved.
- X#
- X# Redistribution and use in source and binary forms are permitted
- X# provided that the above copyright notice and this paragraph are
- X# duplicated in all such forms and that any documentation,
- X# advertising materials, and other materials related to such
- X# distribution and use acknowledge that the software was developed
- X# by the University of California, Riverside.
- X#
- X# NOTE : That's Riverside. Not Berkeley, not Santa Cruz, not even
- X# Irvine. Riverside. Ri - ver - side.
- X#
- X# The name of the University may not be used to endorse or promote
- X# products derived from this software without specific prior written
- X# permission.
- X#
- X# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X# WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X#
- X# MLPD -- Multiple Line Printer Daemon (Version 1.3)
- X# SCCS keywords: @(#)Makefile 1.3 12/1/90
- X#
- X
- X#
- X# Note : Make sure to look in config.h for other parameters.
- X#
- X
- X# Include this line if you are running under the Sun OS environment.
- X# It is designed basically to change from using <sys/dir.h> to using
- X# <dirent.h>, because of the System V compatibility.
- X#
- X# The debug flag is also specified because of some people's desire to
- X# take a small peek at what is going on. You can use it, but it is
- X# very noisy, and shouldn't be used when running normally.
- X#
- XEXTRA_FLAGS = -DSUN #-DDEBUG -g
- X#
- X# And now, the rest of the story.
- X#
- XOBJS = daemon.o lock.o pfile.o mlp.o printcap.o printer.o
- XPROG = mlpd
- XCC = cc
- XCFLAGS = -c $(EXTRA_FLAGS)
- X
- X$(PROG) : $(OBJS)
- X $(CC) -o $(PROG) $(OBJS)
- X
- Xclean :
- X /bin/rm -f *.o $(PROG)
- END_OF_FILE
- if test 1775 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(4085 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1990 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by the University of California, Riverside.
- X *
- X * NOTE : That's Riverside. Not Berkeley, not Santa Cruz, not even
- X * Irvine. Riverside. Ri - ver - side.
- X *
- X * The name of the University may not be used to endorse or promote
- X * products derived from this software without specific prior written
- X * permission.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * MLPD -- Multiple Line Printer Daemon (Version 1.3)
- X * SCCS keywords: @(#)README 1.3 12/1/90
- X */
- X
- XNOTE: This program is in its first testing stages. If I send it out,
- X and people like it, I'll post it to the USENET network. If
- X not, I'll just put it on a resume. This is the first version,
- X and I have already started working on a new version that has
- X many more features, all that remain very simplistic to the
- X user, which is my main objective.
- X
- X
- XNow on with the real important stuff:
- X
- X
- XThis program (MLPD) is a little piece of code I wrote to use a single
- Xprinter queue for a set of multiple printers. It's kind of wierd to
- Xset up, but once it is running, it should help out a lot.
- X
- XHere are the steps for a clean configuration, in proper order :
- X---------------------------------------------------------------
- X
- X1. Edit Makefile to your particular system and needs. If you are running
- X under a SunOS environment, you need to define -DSUN, and if you want
- X to print out hari-kari debug messages, you need to specify -DDEBUG.
- X
- X2. Compile the program, or get it operational. (Whichever comes first.)
- X
- X3. Turn off the printing to the base printer that your employees, friends,
- X or students print to, and turn off queueing on the other printers. For
- X example, 'lp' is your base printer (Where most people type in 'lpr'),
- X and your other printers are the real printers that will be doing the
- X actual printing (like 'lp1', 'lp2', etc.)
- X
- X4. Make sure all of the printers are properly set up in the /etc/printcap
- X so that the printers can run smoothly. Make sure that your main
- X printer ('lp' is your main printer, from #3.) doesn't do any printing
- X and that your other printers area actually connected to the devices.
- X
- X5. Try it out! The command to start off the program is :
- X
- X mlpd -p [<base printer> <printer1> <printer2> ...] [-t <timeout>]
- X
- X For example, a command line following #3 and #4 would be:
- X
- X mlpd -p lp lp1 lp2 -t 5
- X
- X In this example, the main queueing printer is lp, the other printers
- X are lp1 and lp2, and the timeout to check for a print job is 5 seconds.
- X
- X6. If it works, try to set it up in your rc.local to start up when you
- X start up your system. Make sure, however, that you put the mlpd entry
- X after starting up lpd. Otherwise, mlpd will not function.
- X
- XThe program runs under a Sun OS environment. It has been tried out
- Xunder 4.1 SunOS, and I had it tried out under a 4.3 BSD environment,
- Xthanks to the help of nash@ucselx.sdsu.edu (Thanks, Ron!) I hope that
- Xit works for you. Please send me all bug reports, special things that
- Xwould make your life easier, etc., so on, so forth. If you do have any
- Xquestions at all, please mail me to let me know about what you need.
- XI'll be out with a manual page soon enough. (Gotta learn a bit about
- Xnroff...Too much TeX and LaTeX.)
- X
- X--Matt
- X
- X____________________________________________________________________________
- XMatt D. Robinson Internet: yakker@ucrmath.ucr.edu
- XSystems Programming Group, UC Riverside UUCP: ..!ucsd!ucrmath!yakker
- END_OF_FILE
- if test 4085 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'config.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'config.h'\"
- else
- echo shar: Extracting \"'config.h'\" \(1824 characters\)
- sed "s/^X//" >'config.h' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1990 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by the University of California, Riverside.
- X *
- X * NOTE : That's Riverside. Not Berkeley, not Santa Cruz, not even
- X * Irvine. Riverside. Ri - ver - side.
- X *
- X * The name of the University may not be used to endorse or promote
- X * products derived from this software without specific prior written
- X * permission.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * MLPD -- Multiple Line Printer Daemon (Version 1.3)
- X * SCCS keywords: @(#)config.h 1.3 12/1/90
- X */
- X
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <sys/un.h>
- X#include <sys/param.h>
- X#include <sys/ioctl.h>
- X#include <sys/time.h>
- X#include <sys/wait.h>
- X#include <sys/stat.h>
- X#include <syslog.h>
- X#include <time.h>
- X#ifdef SUN
- X#include <dirent.h>
- X#else
- X#include <sys/dir.h>
- X#endif
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <errno.h>
- X
- X#define TRUE 1
- X#define FALSE 0
- X#ifdef DEBUG
- X#define debug(x) fprintf(stderr, "%s", (x))
- X#else
- X#define debug(x) fprintf(stderr, "%s", "")
- X#endif
- X
- Xtypedef struct
- X{
- X char *name[512];
- X char *directory[512];
- X} printerstruct;
- X
- Xextern char *LP_SPOOL_DIRECTORY;
- Xextern int TIMEOUT;
- X
- Xint init_daemon();
- Xint lock_printer();
- Xint bomb();
- Xint check_prs();
- Xint check_base_printer();
- Xvoid exit();
- Xchar *malloc();
- END_OF_FILE
- if test 1824 -ne `wc -c <'config.h'`; then
- echo shar: \"'config.h'\" unpacked with wrong size!
- fi
- # end of 'config.h'
- fi
- if test -f 'daemon.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'daemon.c'\"
- else
- echo shar: Extracting \"'daemon.c'\" \(3479 characters\)
- sed "s/^X//" >'daemon.c' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1990 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by the University of California, Riverside.
- X *
- X * NOTE : That's Riverside. Not Berkeley, not Santa Cruz, not even
- X * Irvine. Riverside. Ri - ver - side.
- X *
- X * The name of the University may not be used to endorse or promote
- X * products derived from this software without specific prior written
- X * permission.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * MLPD -- Multiple Line Printer Daemon (Version 1.3)
- X * SCCS keywords: @(#)daemon.c 1.3 12/1/90
- X */
- X
- X#include "config.h"
- X
- X/*
- X// (int) init_daemon() -- Initialize a process as a daemon process.
- X//
- X// This function will start off by forking a process off from the
- X// parent, and give control over to the child by opening up the
- X// root directory, duplicating stdout and stderr for the child,
- X// and release the terminal control for the main terminal.
- X// The program also calls lock_printer() after the fork(), so that
- X// the child process is saved into a file when the status of the
- X// program needs to be checked.
- X//
- X// Arguments : None
- X*/
- Xint init_daemon(base)
- Xchar *base;
- X{
- X int pid;
- X
- X /*
- X // Fork off a process.
- X */
- X if ((pid = fork()) < 0)
- X {
- X bomb("fork");
- X }
- X /*
- X // First we will check in on the parent, and get rid of it.
- X */
- X if (pid)
- X {
- X exit(0);
- X }
- X /*
- X // Now we specifically want all of the code in the child.
- X // We try to lock down the printer daemon by creating a lock
- X // file.
- X */
- X if (lock_printer(base) < 0)
- X {
- X bomb("lock_printer");
- X }
- X /*
- X // Well, if this returns, then we must start closing off the
- X // terminal control. We call open(), then dup2() for stdout
- X // and stderr, then we try to call setpgrp on the process to
- X // put itself into the background. Only the ioctl call will
- X // release control from the terminal. Then we close the de-
- X // scriptor created by the second open() call.
- X */
- X if (open("/", 0) < 0) { bomb("open"); }
- X if (dup2(0, 1) < 0) { bomb("dup2:stdout"); }
- X if (dup2(0, 2) < 0) { bomb("dup2:stderr"); }
- X if (setpgrp(0, getpid()) < 0) { bomb("setpgrp"); }
- X /*
- X // Well, everything must have worked correctly, so we will default
- X // back to the parent.
- X */
- X}
- X
- X/*
- X// (int) bomb() -- Display an error message, then exit.
- X//
- X// bomb() simply will call perror() and send the function call a string
- X// declaring the error to be displayed to the user. Once this returns
- X// we can then call exit().
- X//
- X// Arguments : char *str (The string message to be displayed)
- X*/
- Xint bomb(str)
- Xchar *str;
- X{
- X char buf[1024];
- X time_t now;
- X struct tm *nowtime;
- X
- X
- X buf[0] = '\0';
- X (void)perror(str);
- X now = (time_t)time();
- X nowtime = localtime(&now);
- X (void)sprintf(buf, "Date: (%d/%d/%d)\n\
- X Time: (%d:%d:%d)\n\
- X Message: Process died from error message (%s)\n\n",
- X nowtime->tm_mon, nowtime->tm_mday, nowtime->tm_year,
- X nowtime->tm_hour, nowtime->tm_min, nowtime->tm_sec,
- X str);
- X (void)openlog("mlpd", LOG_PID, LOG_LPR);
- X (void)syslog(LOG_ERR, buf);
- X (void)closelog();
- X (void)exit(1);
- X}
- END_OF_FILE
- if test 3479 -ne `wc -c <'daemon.c'`; then
- echo shar: \"'daemon.c'\" unpacked with wrong size!
- fi
- # end of 'daemon.c'
- fi
- if test -f 'lock.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'lock.c'\"
- else
- echo shar: Extracting \"'lock.c'\" \(3637 characters\)
- sed "s/^X//" >'lock.c' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1990 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by the University of California, Riverside.
- X *
- X * NOTE : That's Riverside. Not Berkeley, not Santa Cruz, not even
- X * Irvine. Riverside. Ri - ver - side.
- X *
- X * The name of the University may not be used to endorse or promote
- X * products derived from this software without specific prior written
- X * permission.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * MLPD -- Multiple Line Printer Daemon (Version 1.3)
- X * SCCS keywords: @(#)lock.c 1.3 12/1/90
- X */
- X
- X#include "config.h"
- X
- X/*
- X// lock_printer() -- Lock up the printer daemon for once per machine.
- X//
- X// The lock_printer() process will try to save the pid of the process
- X// that is about to run to a file, to reference later when we need to
- X// check to see if the program is running (We do not want to let the
- X// program run more than once per machine.)
- X//
- X// Arguments : None
- X*/
- Xint lock_printer(base)
- Xchar *base;
- X{
- X FILE *fp, *fopen();
- X void exit();
- X char buf[1024];
- X int pid;
- X
- X /*
- X // First we will try to fopen() the file. If we can't get
- X // the file open, we have to assume that either the file has
- X // been moved, or the program has been recompiled and there
- X // is a new lock file directory. If we can fopen() it,
- X // we will run through this [if..then] loop and handle the
- X // conditions.
- X */
- X buf[0] = '\0';
- X (void)sprintf(buf, "/etc/mlpd.%s.pid", base);
- X if ((fp = fopen(buf, "r")) != NULL)
- X {
- X /*
- X // Try to read the number from the file.
- X */
- X if (fscanf(fp, "%d", &pid) < 0)
- X {
- X perror("lock_printer:fscanf:fopen");
- X exit(-1);
- X }
- X /*
- X // If we can read the number, then we need to see whether
- X // the process still exists. If it does, then we want to
- X // Just exit out, and tell the user that the program is
- X // still running; otherwise, we need to clean up the file
- X // that exists in the directory, and create the file showing
- X // the new PID in the file.
- X */
- X if (getpgrp(pid) >= 0)
- X {
- X if (fprintf(stderr, "This program is already running \
- X (PID# : %d)\n", pid) < 0)
- X {
- X bomb("lock_printer");
- X }
- X exit(1);
- X }
- X }
- X /*
- X // If we got to this point in the code, then either there wasn't a
- X // lock file in the directory, or the process which was running
- X // died off. In either case, remove the file that we found, if
- X // there.
- X */
- X if (unlink(buf) < 0)
- X {
- X /*
- X // Do nothing. We want to try to remove the
- X // file no matter what.
- X */
- X }
- X /*
- X // Now we want to try and fopen the file for writing. This is
- X // to place the present getpid() into the file for reference
- X // later.
- X */
- X if ((fp = fopen(buf, "w")) == NULL)
- X {
- X bomb("lock_printer:/etc/mlpd.pid:fopen");
- X }
- X /*
- X // Try to fprintf() the getpid() return value into the file.
- X */
- X if (fprintf(fp, "%d", getpid()) < 0)
- X {
- X bomb("lock_printer:fprintf");
- X }
- X /*
- X // If we get here, all we have to do is close the file, and
- X // go back to the init_daemon() process.
- X */
- X if (fclose(fp) < 0)
- X {
- X bomb("lock_printer:fclose");
- X }
- X /*
- X // Well, everything must have worked, so we'll just head back and
- X // tell the calling program that everything is okay.
- X */
- X return 1;
- X}
- END_OF_FILE
- if test 3637 -ne `wc -c <'lock.c'`; then
- echo shar: \"'lock.c'\" unpacked with wrong size!
- fi
- # end of 'lock.c'
- fi
- if test -f 'mlp.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mlp.c'\"
- else
- echo shar: Extracting \"'mlp.c'\" \(4126 characters\)
- sed "s/^X//" >'mlp.c' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1990 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by the University of California, Riverside.
- X *
- X * NOTE : That's Riverside. Not Berkeley, not Santa Cruz, not even
- X * Irvine. Riverside. Ri - ver - side.
- X *
- X * The name of the University may not be used to endorse or promote
- X * products derived from this software without specific prior written
- X * permission.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * MLPD -- Multiple Line Printer Daemon (Version 1.3)
- X * SCCS keywords: @(#)mlp.c 1.3 12/1/90
- X */
- X
- X#include "config.h"
- Xchar *LP_SPOOL_DIRECTORY;
- Xint TIMEOUT;
- Xint errno;
- X
- X/*
- X// main() -- The main program.
- X//
- X// This will start off looking to create the printer structure,
- X// initialize the process so that it is running as a daemon,
- X// find the total number of printers to check, and start up a
- X// select/test loop that looks for print jobs in the main queue
- X// and moves/prints the new files in new queues.
- X//
- X// Arguments : None
- X*/
- Xint main(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int count, clt, nready, pready, no_of_printers;
- X struct timeval timeout;
- X printerstruct *printers;
- X#ifndef lint
- X FILE *myfp, *fopen();
- X#endif
- X int fprintf();
- X int write();
- X void exit();
- X
- X /*
- X // First, initialize the printer structure.
- X */
- X#ifdef lint
- X printers = NULL;
- X#else
- X printers = (printerstruct *) malloc(sizeof(printerstruct));
- X#endif
- X /*
- X // Next, parse through all of the arguments to find information
- X // that we need, and set all variables necessary.
- X */
- X no_of_printers = parse_arguments(argc, argv, printers);
- X /*
- X // Set the timeout values for the select process to be 2 seconds,
- X // which keeps the CPU usage down.
- X */
- X timeout.tv_sec = 2;
- X timeout.tv_usec = 0;
- X count = 0;
- X while(TRUE)
- X {
- X /*
- X // Do a select() for about 2 seconds on nothing, so that
- X // all we do is a time wait without causing a lot of CPU
- X // usage. I'm hoping that this isn't too much bother for
- X // the users.
- X */
- X if (count == 0)
- X {
- X (void)restart_all_printers(no_of_printers, printers);
- X /*
- X // (15 * 2 seconds) + 2 seconds;
- X */
- X count = 16;
- X }
- X --count;
- X if ((nready = select((int) 0, (fd_set *) NULL, (fd_set *) NULL,
- X (fd_set *) NULL, (struct timeval *) &timeout)) < 0)
- X {
- X if (errno != EINTR)
- X {
- X bomb("select");
- X }
- X else
- X {
- X nready = 0;
- X }
- X }
- X /*
- X // Well, from here, we want to go through the printers
- X // to make sure we either don't have anything to print,
- X // or all of the printers are busy. We check the base
- X // printer (Which ever one that is), and see if it has
- X // any files to print. If it does, then we want to print
- X // out the file to one of the other printers, if any
- X // of them are available.
- X */
- X pready = 0;
- X while ((nready == 0) &&
- X (check_base_printer() > 0) &&
- X (pready == 0))
- X {
- X debug("Found a file to print.\n");
- X /*
- X // Begin to check through the list of printers
- X // and see if we have one free. If we do, print
- X // to that printer, otherwise, skip it. We do
- X // NOT want to queue files on printers...We want
- X // to maintain one queue. (See README).
- X */
- X for (clt = 0; clt < no_of_printers; ++clt)
- X {
- X /*
- X // This checks to see if the printer is
- X // available to print on.
- X */
- X if ((pready = check_prs(printers, clt)) < 0)
- X {
- X bomb("check_prs");
- X }
- X else if (pready == 0)
- X {
- X debug("I can print out a file.\n");
- X /*
- X // If we get here, we can print
- X // out a file on this printer.
- X */
- X if (print_file(printers, clt) < 0)
- X {
- X bomb("print_file");
- X }
- X clt = no_of_printers;
- X }
- X }
- X }
- X }
- X}
- END_OF_FILE
- if test 4126 -ne `wc -c <'mlp.c'`; then
- echo shar: \"'mlp.c'\" unpacked with wrong size!
- fi
- # end of 'mlp.c'
- fi
- if test -f 'mlpd.8' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mlpd.8'\"
- else
- echo shar: Extracting \"'mlpd.8'\" \(3786 characters\)
- sed "s/^X//" >'mlpd.8' <<'END_OF_FILE'
- X.\" Copyright (c) 1983 Regents of the University of California.
- X.\" All rights reserved. The Berkeley software License Agreement
- X.\" specifies the terms and conditions for redistribution.
- X.\"
- X.\" @(#)mlpd.8 1.3 12/1/90; from UCR SunOS 4.1
- X.\"
- X.TH MLPD 8 "8 November 1990"
- X.SH NAME
- Xmlpd \- multiple line printer daemon
- X.SH SYNOPSIS
- X
- X.B mlpd
- X[
- X.B \-p <base pr> <pr1> <pr2> ...
- X] [
- X.B \-t <timeout>
- X]
- X.SH DESCRIPTION
- X
- X.LP
- X.B mlpd
- Xis a multiple line printer daemon, which is set up in your
- Xrc.local (read the manual on rc (8)) script, which will monitor files
- Xbeing printed on your system. mlpd will look in the base printer
- Xdirectory for files, try to find jobs that need to be printed, and
- Xtake those jobs and move them to any available printers. Printer jobs
- Xno longer have to wait for a larger job in front of them. This allows
- Xfor optimization in printing files to any number of printers.
- X
- X.SH OPTIONS
- X
- X.LP
- X.SS \-p <base pr> <pr1> <pr2> ...
- X
- X.LP
- XSpecifies the printers to print on. For example, if lp is the
- Xnormal line printer to queue to, and the real printers are connected
- Xlp1 and lp2, then I would specify
- X.B \-p lp lp1 lp2
- Xas my print options. The super-user can specify any number of printers
- Xfrom the command line. The program will look up these printers in
- X/etc/printcap entry to verify their existance, and use their
- Xspooling directories as the directories to queue in. If the printers
- Xare not in /etc/printcap, or the proper spooling directories do not
- Xexist, then the program will exit and log all information to syslog().
- X.LP
- X.SS \-t <timeout>
- X
- X.LP
- XSpecifies the amount of time to wait before checking the base printer
- Xqueue. Normally this time is set to 2 seconds, but the user can specify
- Xwhat they wish. It is normally suggested to let the default remain intact,
- Xas the program will run better under this environment.
- X.SH OPERATION
- X.SS Operation/Syntax of Program
- X.LP
- XThe program runs by first trying to check all of the command line arguments,
- Xand setting all of the proper printing options. Once it knows where each
- Xprinter queueing directory is, it then goes out and starts into a loop,
- Xwhere is calls select() for a period of seconds equal to that specified on
- Xthe command line, or a default of 2 seconds. After the timeout has occurred,
- Xthe daemon will go out and look for jobs in the base printer queue. If
- Xit finds any jobs, it will then check to see if any of the printers specified
- Xare available for printing. If one of the printers is free to print, it
- Xwill send that printer the print job first available. It will continue to
- Xdo this until either there are no more jobs in the printer queue, or all
- Xof the printers are busy. Every 30 seconds, the printers are restarted
- Xagain, in case any printer files become jammed for some reason. Should
- Xthe super-user want to kill off the program, there will be a lock file in
- X/etc with the name "mlpd.<base pr>.pid", which will contain the PID of
- Xthe daemon running.
- X
- X.SH "SEE ALSO"
- X.BR lpq (1),
- X.BR lpr (1),
- X.BR lprm (1),
- X.BR hosts (5),
- X.BR hosts.equiv (5),
- X.BR printcap (5),
- X.BR lpc (8),
- X.BR pac (8)
- X.SH BUGS
- X
- XThe program can only allow for 512 printers. If you can edit the code,
- Xyou can raise this amount, but I really didn't imagine someone trying
- Xto watch over more than 512 printers.
- X
- XIf you start up mlpd before starting up lpd in rc.local, the program
- Xwill exit, because it was not able to connect to the lpd device.
- X
- XThe timeout value is set to 2 seconds, so if this begins to slow your
- Xsystem down, increase this value. I would not suggest lowering it.
- X
- XIf you find something else wrong with it, please let me know. I'm ever
- Xwilling to fix anything wrong with it, add new functionality, and so forth.
- XContact yakker@ucrmath.ucr.edu for any other information, bug reports, etc.
- END_OF_FILE
- if test 3786 -ne `wc -c <'mlpd.8'`; then
- echo shar: \"'mlpd.8'\" unpacked with wrong size!
- fi
- # end of 'mlpd.8'
- fi
- if test -f 'pfile.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'pfile.c'\"
- else
- echo shar: Extracting \"'pfile.c'\" \(4610 characters\)
- sed "s/^X//" >'pfile.c' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1990 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by the University of California, Riverside.
- X *
- X * NOTE : That's Riverside. Not Berkeley, not Santa Cruz, not even
- X * Irvine. Riverside. Ri - ver - side.
- X *
- X * The name of the University may not be used to endorse or promote
- X * products derived from this software without specific prior written
- X * permission.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * MLPD -- Multiple Line Printer Daemon (Version 1.3)
- X * SCCS keywords: @(#)pfile.c 1.3 12/1/90
- X */
- X
- X#include "config.h"
- Xextern char *LP_SPOOL_DIRECTORY;
- Xextern int TIMEOUT;
- X
- X/*
- X// parse_arguments() -- Get printer information from argv.
- X//
- X// This function when called will return a structure containing
- X// the printers and their respective spooling directories in
- X// a structure.
- X//
- X// Arguments : printerstruct *printers (The printer structure)
- X*/
- Xint parse_arguments(argc, argv, printers)
- Xint argc;
- Xchar *argv[];
- Xprinterstruct *printers;
- X{
- X int i, origargc;
- X int no_of_printers, ncnt, can_exit;
- X char base[1024];
- X
- X can_exit = FALSE;
- X i = 0;
- X origargc = argc;
- X if (argc < 5)
- X {
- X usage(argv[0], "Not enough arguments.\n");
- X }
- X while (--argc)
- X {
- X if (!strcmp("-t", argv[i]))
- X {
- X if ((atoi(argv[i+1])) && (i+1 != argc))
- X {
- X TIMEOUT = atoi(argv[i + 1]);
- X }
- X else
- X {
- X usage(argv[0], "Bad timeout value.\n");
- X }
- X }
- X if (!strcmp("-p", argv[i]))
- X {
- X can_exit = TRUE;
- X no_of_printers = 0;
- X for (ncnt = i + 1; ncnt < origargc; ++ncnt)
- X {
- X if (!strcmp(argv[ncnt], "-t"))
- X {
- X ncnt = origargc;
- X }
- X else if (ncnt == i + 1)
- X {
- X (void)strcpy(base, argv[ncnt]);
- X find_pr(argv[ncnt]);
- X }
- X else
- X {
- X add_pr(printers, argv[ncnt],
- X no_of_printers);
- X ++no_of_printers;
- X }
- X }
- X if (no_of_printers < 2)
- X {
- X usage(argv[0], "Less than 2 printers specified.\n");
- X }
- X }
- X ++i;
- X }
- X if (!TIMEOUT) TIMEOUT = 2;
- X if (can_exit == FALSE)
- X {
- X usage(argv[0], "Bad arguments used. Must use -p option.\n");
- X }
- X init_daemon(base);
- X return(no_of_printers);
- X}
- X
- Xusage(arg, str)
- Xchar *arg, *str;
- X{
- X (void)fprintf(stderr, "%sUsage : %s [-p <main printer> <pr1> <pr2> ...] [-t <timeout>]\n", str, arg);
- X exit(1);
- X}
- X
- X/*
- X// add_pr() - add a printer to the list of printers.
- X//
- X// Arguments : printerstruct *printers -- the printer structure.
- X// char *str -- the name of the printer specified on command line.
- X// int nop -- the number of the printer item;
- X*/
- Xint add_pr(printers, str, nop)
- Xprinterstruct *printers;
- Xchar *str;
- Xint nop;
- X{
- X char line[BUFSIZ];
- X char *tmpbuf;
- X int status;
- X char *bp;
- X
- X#ifndef lint
- X printers->directory[nop] = (char *) malloc(512);
- X printers->name[nop] = (char *) malloc(512);
- X tmpbuf = (char *)malloc(BUFSIZ);
- X bp = (char *)malloc(BUFSIZ/2);
- X#else
- X printers->directory[nop] = NULL;
- X printers->name[nop] = NULL;
- X tmpbuf = NULL;
- X bp = NULL;
- X#endif
- X if ((status = pgetent(line, str)) < 0)
- X {
- X bomb("pgetent");
- X }
- X if (status == 0)
- X {
- X (void)fprintf(stderr, "No such printer (%s) exists on this system.\n", str);
- X exit(1);
- X }
- X if ((tmpbuf = (char *)pgetstr((char *)"sd", (char *)&bp)) == NULL)
- X {
- X bomb("get_prdir_from_printcap:pgetstr");
- X }
- X (void)strcpy((char *)printers->directory[nop], (char *)tmpbuf);
- X (void)strcpy((char *)printers->name[nop], (char *)str);
- X}
- X
- X/*
- X// find_pr() - find the base printer in the printcap file.
- X//
- X// This function will set the LP_SPOOL_DIRECTORY to the base printer
- X// spooling directory specified in /etc/printcap.
- X//
- X// Arguments : char *str -- the name of the printer specified on command line.
- X*/
- X
- Xfind_pr(str)
- Xchar *str;
- X{
- X char line[BUFSIZ];
- X#ifndef lint
- X char *newdir;
- X char *bp;
- X#endif
- X int status;
- X
- X#ifndef lint
- X newdir = (char *)malloc(BUFSIZ);
- X bp = (char *)malloc(BUFSIZ/2);
- X#endif
- X if ((status = pgetent(line, str)) < 0)
- X {
- X bomb("pgetent");
- X }
- X if (status == 0)
- X {
- X (void)fprintf(stderr, "No such printer (%s) exists on this system.\n", str);
- X exit(1);
- X }
- X if ((newdir = (char *)pgetstr("sd", &bp)) == NULL)
- X {
- X bomb("get_prdir_from_printcap:pgetstr");
- X }
- X LP_SPOOL_DIRECTORY = (char *)strdup(newdir);
- X}
- END_OF_FILE
- if test 4610 -ne `wc -c <'pfile.c'`; then
- echo shar: \"'pfile.c'\" unpacked with wrong size!
- fi
- # end of 'pfile.c'
- fi
- if test -f 'printcap.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'printcap.c'\"
- else
- echo shar: Extracting \"'printcap.c'\" \(6858 characters\)
- sed "s/^X//" >'printcap.c' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1983 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by the University of California, Berkeley. The name of the
- X * University may not be used to endorse or promote products derived
- X * from this software without specific prior written permission.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)printcap.c 5.3 (Berkeley) 6/30/88";
- X#endif /* not lint */
- X
- X#define BUFSIZ 1024
- X#define MAXHOP 32 /* max number of tc= indirections */
- X
- X#include <ctype.h>
- X#include <stdio.h>
- X/*
- X * termcap - routines for dealing with the terminal capability data base
- X *
- X * BUG: Should use a "last" pointer in tbuf, so that searching
- X * for capabilities alphabetically would not be a n**2/2
- X * process when large numbers of capabilities are given.
- X * Note: If we add a last pointer now we will screw up the
- X * tc capability. We really should compile termcap.
- X *
- X * Essentially all the work here is scanning and decoding escapes
- X * in string capabilities. We don't use stdio because the editor
- X * doesn't, and because living w/o it is not hard.
- X */
- X
- X#define PRINTCAP
- X
- X#ifdef PRINTCAP
- X#define tgetent pgetent
- X#define tskip pskip
- X#define tgetstr pgetstr
- X#define tdecode pdecode
- X#define tdecode pdecode
- X#define tnchktc pnchktc
- X#define tnamatch pnamatch
- X#undef E_TERMCAP
- X#define E_TERMCAP "/etc/printcap"
- X#define V6
- X#endif
- X
- Xstatic char *tbuf;
- Xstatic int hopcount; /* detect infinite loops in termcap, init 0 */
- Xchar *tskip();
- Xchar *tgetstr();
- Xchar *tdecode();
- Xchar *getenv();
- X
- X/*
- X * Get an entry for terminal name in buffer bp,
- X * from the termcap file. Parse is very rudimentary;
- X * we just notice escaped newlines.
- X */
- Xtgetent(bp, name)
- X char *bp, *name;
- X{
- X register char *cp;
- X register int c;
- X register int i = 0, cnt = 0;
- X char ibuf[BUFSIZ];
- X#ifndef lint
- X char *cp2;
- X#endif
- X int tf;
- X
- X tbuf = bp;
- X tf = 0;
- X#ifndef V6
- X cp = getenv("TERMCAP");
- X /*
- X * TERMCAP can have one of two things in it. It can be the
- X * name of a file to use instead of /etc/termcap. In this
- X * case it better start with a "/". Or it can be an entry to
- X * use so we don't have to read the file. In this case it
- X * has to already have the newlines crunched out.
- X */
- X if (cp && *cp) {
- X if (*cp!='/') {
- X cp2 = getenv("TERM");
- X if (cp2==(char *) 0 || strcmp(name,cp2)==0) {
- X (void)strcpy(bp,cp);
- X return(tnchktc());
- X } else {
- X tf = open(E_TERMCAP, 0);
- X }
- X } else
- X tf = open(cp, 0);
- X }
- X if (tf==0)
- X tf = open(E_TERMCAP, 0);
- X#else
- X tf = open(E_TERMCAP, 0);
- X#endif
- X if (tf < 0)
- X return (-1);
- X for (;;) {
- X cp = bp;
- X for (;;) {
- X if (i == cnt) {
- X cnt = read(tf, ibuf, BUFSIZ);
- X if (cnt <= 0) {
- X (void)close(tf);
- X return (0);
- X }
- X i = 0;
- X }
- X c = ibuf[i++];
- X if (c == '\n') {
- X if (cp > bp && cp[-1] == '\\'){
- X cp--;
- X continue;
- X }
- X break;
- X }
- X if (cp >= bp+BUFSIZ) {
- X (void)write(2,"Termcap entry too long\n", 23);
- X break;
- X } else
- X *cp++ = c;
- X }
- X *cp = 0;
- X
- X /*
- X * The real work for the match.
- X */
- X if (tnamatch(name)) {
- X (void)close(tf);
- X return(tnchktc());
- X }
- X }
- X}
- X
- X/*
- X * tnchktc: check the last entry, see if it's tc=xxx. If so,
- X * recursively find xxx and append that entry (minus the names)
- X * to take the place of the tc=xxx entry. This allows termcap
- X * entries to say "like an HP2621 but doesn't turn on the labels".
- X * Note that this works because of the left to right scan.
- X */
- Xtnchktc()
- X{
- X register char *p, *q;
- X char tcname[16]; /* name of similar terminal */
- X char tcbuf[BUFSIZ];
- X char *holdtbuf = tbuf;
- X int l;
- X
- X p = tbuf + strlen(tbuf) - 2; /* before the last colon */
- X while (*--p != ':')
- X if (p<tbuf) {
- X (void)write(2, "Bad termcap entry\n", 18);
- X return (0);
- X }
- X p++;
- X /* p now points to beginning of last field */
- X if (p[0] != 't' || p[1] != 'c')
- X return(1);
- X (void)strcpy(tcname,p+3);
- X q = tcname;
- X while (q && *q != ':')
- X q++;
- X *q = 0;
- X if (++hopcount > MAXHOP) {
- X (void)write(2, "Infinite tc= loop\n", 18);
- X return (0);
- X }
- X if (tgetent(tcbuf, tcname) != 1)
- X return(0);
- X for (q=tcbuf; *q != ':'; q++)
- X ;
- X l = p - holdtbuf + strlen(q);
- X if (l > BUFSIZ) {
- X (void)write(2, "Termcap entry too long\n", 23);
- X q[BUFSIZ - (p-tbuf)] = 0;
- X }
- X (void)strcpy(p, q+1);
- X tbuf = holdtbuf;
- X return(1);
- X}
- X
- X/*
- X * Tnamatch deals with name matching. The first field of the termcap
- X * entry is a sequence of names separated by |'s, so we compare
- X * against each such name. The normal : terminator after the last
- X * name (before the first field) stops us.
- X */
- Xtnamatch(np)
- X char *np;
- X{
- X register char *Np, *Bp;
- X
- X Bp = tbuf;
- X if (*Bp == '#')
- X return(0);
- X for (;;) {
- X for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
- X continue;
- X if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
- X return (1);
- X while (*Bp && *Bp != ':' && *Bp != '|')
- X Bp++;
- X if (*Bp == 0 || *Bp == ':')
- X return (0);
- X Bp++;
- X }
- X}
- X
- X/*
- X * Skip to the next field. Notice that this is very dumb, not
- X * knowing about \: escapes or any such. If necessary, :'s can be put
- X * into the termcap file in octal.
- X */
- Xstatic char *
- Xtskip(bp)
- X register char *bp;
- X{
- X
- X while (*bp && *bp != ':')
- X bp++;
- X if (*bp == ':')
- X bp++;
- X return (bp);
- X}
- X
- X/*
- X * Get a string valued option.
- X * These are given as
- X * cl=^Z
- X * Much decoding is done on the strings, and the strings are
- X * placed in area, which is a ref parameter which is updated.
- X * No checking on area overflow.
- X */
- Xchar *
- Xtgetstr(id, area)
- X char *id, **area;
- X{
- X register char *bp = tbuf;
- X
- X for (;;) {
- X bp = tskip(bp);
- X if (!*bp)
- X return (0);
- X if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
- X continue;
- X if (*bp == '@')
- X return(0);
- X if (*bp != '=')
- X continue;
- X bp++;
- X return (tdecode(bp, area));
- X }
- X}
- X
- X/*
- X * Tdecode does the grung work to decode the
- X * string capability escapes.
- X */
- Xstatic char *
- Xtdecode(str, area)
- X register char *str;
- X char **area;
- X{
- X register char *cp;
- X register int c;
- X register char *dp;
- X int i;
- X
- X cp = *area;
- X while ((c = *str++) && c != ':') {
- X switch (c) {
- X
- X case '^':
- X c = *str++ & 037;
- X break;
- X
- X case '\\':
- X dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
- X c = *str++;
- Xnextc:
- X if (*dp++ == c) {
- X c = *dp++;
- X break;
- X }
- X dp++;
- X if (*dp)
- X goto nextc;
- X if (isdigit(c)) {
- X c -= '0', i = 2;
- X do
- X c <<= 3, c |= *str++ - '0';
- X while (--i && isdigit(*str));
- X }
- X break;
- X }
- X *cp++ = c;
- X }
- X *cp++ = 0;
- X str = *area;
- X *area = cp;
- X return (str);
- X}
- END_OF_FILE
- if test 6858 -ne `wc -c <'printcap.c'`; then
- echo shar: \"'printcap.c'\" unpacked with wrong size!
- fi
- # end of 'printcap.c'
- fi
- if test -f 'printer.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'printer.c'\"
- else
- echo shar: Extracting \"'printer.c'\" \(9835 characters\)
- sed "s/^X//" >'printer.c' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1990 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by the University of California, Riverside.
- X *
- X * NOTE : That's Riverside. Not Berkeley, not Santa Cruz, not even
- X * Irvine. Riverside. Ri - ver - side.
- X *
- X * The name of the University may not be used to endorse or promote
- X * products derived from this software without specific prior written
- X * permission.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * MLPD -- Multiple Line Printer Daemon (Version 1.3)
- X * SCCS keywords: @(#)printer.c 1.3 12/1/90
- X */
- X
- X#include "config.h"
- X
- X/*
- X// check_base_printer() -- Check the main printer queue.
- X//
- X// This function will go through the main printer queue and see
- X// whether or not there are any files to print out. If there are,
- X// notify the main program the number of files to print out. We
- X// mainly want to see that there are files to print, so that all
- X// of the other printer queues can be checked.
- X*/
- X
- Xint check_base_printer()
- X{
- X#ifdef SUN
- X struct dirent *d;
- X#else
- X struct direct *d;
- X#endif
- X DIR *dirpointer;
- X int nitems;
- X
- X /*
- X // First we open up the spooling directory for the main
- X // spooler. Queueing should be allowed on this printer,
- X // but printing should be turned off. We open up the
- X // directory to read the files in them.
- X */
- X (void)debug("Checking base printer spooling directory...\n");
- X if ((dirpointer = opendir(LP_SPOOL_DIRECTORY)) == NULL)
- X {
- X debug("Couldn't open directory.\n");
- X return -1;
- X }
- X nitems = 0;
- X /*
- X // Now, while we have the chance, let's check out the files
- X // in the directory and see whether something is printing or
- X // not (if nothing is printing, there won't be any files in
- X // the directory. lpd will delete them off.)
- X */
- X while ((d = readdir(dirpointer)) != NULL)
- X {
- X debug("Checking files in directory.\n");
- X /*
- X // See if the file has a df* extension.
- X // This is the type of file that we want to use to
- X // print out.
- X */
- X if (!strncmp(d->d_name, "cf", 2))
- X {
- X debug("Incrementing file count.\n");
- X ++nitems;
- X }
- X }
- X /*
- X // Now close off the directory, and get back to main().
- X */
- X (void)closedir(dirpointer);
- X return (nitems);
- X}
- X
- X/*
- X// check_prs() -- Check each printer queue.
- X//
- X// This function will go through the each printer queue and see
- X// whether or not there are any files to print out. If there are,
- X// notify the main program the printer is busy, otherwise tell the
- X// main program that we would like a print job sent to us. All of
- X// the printer queues are checked through this machine.
- X*/
- X
- Xint check_prs(printers, cnt)
- Xprinterstruct *printers;
- Xint cnt;
- X{
- X#ifdef SUN
- X struct dirent *d;
- X#else
- X struct direct *d;
- X#endif
- X DIR *dirpointer;
- X int nitems;
- X
- X /*
- X // Try and create a char[] for the directory where
- X // the printer is located.
- X */
- X /*
- X // First we open up the spooling directory for our new
- X // spooler. Printing should be allowed on this printer,
- X // but queueing should be turned off. We open up the
- X // directory to read the files in them.
- X */
- X if ((dirpointer = opendir(printers->directory[cnt])) == NULL)
- X {
- X bomb("check_prs:opendir");
- X return -1;
- X }
- X nitems = 0;
- X /*
- X // Now, while we have the chance, let's check out the files
- X // in the directory and see whether something is printing or
- X // not. If something is printing, then we don't want to send
- X // a job to this printer. If nothing is printing, we want
- X // to ship out a job to the printer ASAP.
- X */
- X while ((d = readdir(dirpointer)) != NULL)
- X {
- X if (!strncmp(d->d_name, "cf", 2))
- X {
- X ++nitems;
- X }
- X }
- X /*
- X // Close off the directory pointer.
- X */
- X (void)closedir(dirpointer);
- X /*
- X // Return the number of files that are printing.
- X */
- X return(nitems);
- X}
- X
- X/*
- X// print_file() -- Print out a file in the spool directory.
- X//
- X// First, we try to find a file in the directory where we have
- X// specified that we are going to print from. If we do, then we
- X// take the job from one printer area to another, and "kick-start"
- X// the new printer into printing out the jobs (We should have to
- X// send a signal to lpd to get this job running.)
- X*/
- X
- Xint print_file(p, cnt)
- Xprinterstruct *p;
- Xint cnt;
- X{
- X#ifdef SUN
- X struct dirent *d;
- X#else
- X struct direct *d;
- X#endif
- X DIR *dirpointer;
- X int nitems;
- X
- X /*
- X // Open up the spooling directory.
- X */
- X (void)debug("Yes, I can now print out a file!\n");
- X if ((dirpointer = opendir(LP_SPOOL_DIRECTORY)) == NULL)
- X {
- X return -1;
- X }
- X nitems = 0;
- X /*
- X // Try to find some number of files to print out on the
- X // printer. If we find a file, we send that file to the new
- X // directory, and send a signal to the lpd program and
- X // return back to the main program. If we do not get any
- X // file from the directory, something must be messed up, so
- X // we need to return our exit status to the main program.
- X // While we are at it, we should pass along the control file
- X // that goes with the data file, so that the printer can get
- X // the proper information for the banner page, accounting, etc.
- X */
- X while (((d = readdir(dirpointer)) != NULL) && (nitems == 0))
- X {
- X /*
- X // Check to see that the file we want to print
- X // is a data file type in the directory.
- X */
- X if (!strncmp(d->d_name, "cf", 2))
- X {
- X /*
- X // Move the files.
- X */
- X (void)debug("I am now attempting to move the files.\n");
- X move_files(d->d_name, p, cnt);
- X /*
- X // Send off the signal to the lpd program.
- X // We never use the return value, though.
- X */
- X (void)debug("Starting up the printer.\n");
- X (void)send_lpd_signal(p->name[cnt]);
- X ++nitems;
- X }
- X }
- X /*
- X // Close off the directory.
- X */
- X (void)closedir(dirpointer);
- X if (nitems == 0)
- X {
- X bomb("readdir");
- X }
- X return(0);
- X}
- X
- X/*
- X// move_files() -- move the files from one spooling directory to another.
- X//
- X// This function will move all of the files associated with a print job
- X// to a new spooling directory.
- X//
- X// Arguments: char *cffile -- the name of the control file.
- X// printerstruct *p -- the printers structure.
- X// int cnt -- the index into printerstruct specifying the printer
- X// directory to move the files to.
- X*/
- Xmove_files(cffile, p, cnt)
- Xchar *cffile;
- Xprinterstruct *p;
- Xint cnt;
- X{
- X char tmpbuf1[1024],tmpbuf2[1024],xbuf[1024],data[1024];
- X FILE *fp, *fopen();
- X
- X xbuf[0] = '\0'; data[0] = '\0';
- X (void)sprintf(xbuf, "%s/%s", LP_SPOOL_DIRECTORY, cffile);
- X (void)debug("Opening and reading control file");
- X if ((fp = fopen(xbuf, "r")) == NULL)
- X {
- X (void)debug("Bombing on fopen().\n");
- X bomb("move_files:fopen");
- X }
- X data[0] = '\0';
- X while (fgets(data, 1024, fp) > 0)
- X {
- X if (data[0] == 'f')
- X {
- X /*
- X // Must be a file that we want...Move it.
- X */
- X (void)debug("Moving data file.\n");
- X tmpbuf1[0] = '\0'; tmpbuf2[0] = '\0';
- X data[strlen(data)-1] = '\0';
- X (void)sprintf(tmpbuf1,"%s/%s",LP_SPOOL_DIRECTORY,&data[1]);
- X (void)sprintf(tmpbuf2,"%s/%s",p->directory[cnt],&data[1]);
- X if (rename(tmpbuf1, tmpbuf2) != 0)
- X {
- X bomb("move_files:fgets:rename");
- X }
- X }
- X data[0] = '\0';
- X }
- X (void)fclose(fp);
- X tmpbuf1[0] = '\0'; tmpbuf2[0] = '\0';
- X (void)sprintf(tmpbuf1, "%s/%s", LP_SPOOL_DIRECTORY,cffile);
- X (void)sprintf(tmpbuf2, "%s/%s", p->directory[cnt],cffile);
- X (void)debug("Moving control file.\n");
- X if (rename(tmpbuf1, tmpbuf2) != 0)
- X {
- X bomb("move_files:rename");
- X }
- X}
- X
- X/*
- X// restart_all_printers() -- send a signal to restart all printers.
- X//
- X// We want to restart all printers when we first start up so that we can
- X// clear jobs from those queues. This will be run every 30 seconds.
- X//
- X// Arguments: int nop -- The total number of printers.
- X// printerstruct *printers -- the printers structure.
- X*/
- X
- Xint restart_all_printers(nop, printers)
- Xint nop;
- Xprinterstruct *printers;
- X{
- X int clt;
- X
- X for (clt = 0; clt < nop; ++clt)
- X {
- X (void)send_lpd_signal(printers->name[clt]);
- X }
- X}
- X
- X/*
- X// send_lpd_signal() -- Send a signal to lpd to start printing from a printer.
- X//
- X// This function will create a socket, try and connect using that socket to
- X// the default socket for the printer, and then if a connection can be made,
- X// the printer is sent a control code to print out all files for a specific
- X// printer. If this returns a \0, then everything was okay.
- X//
- X// Arguments : char *printer; (Name of the printer to use)
- X*/
- X
- Xint send_lpd_signal(printer)
- Xchar *printer;
- X{
- X struct sockaddr_un server;
- X register int s, n;
- X char buf[1024];
- X
- X s = socket(AF_UNIX, SOCK_STREAM, 0);
- X if (s < 0)
- X {
- X if (errno == EMFILE)
- X {
- X bomb("send_lpd_signal:socket:EMFILE");
- X }
- X else if (errno == ENFILE)
- X {
- X bomb("send_lpd_signal:socket:ENFILE");
- X }
- X else if (errno == ENOBUFS)
- X {
- X bomb("send_lpd_signal:socket:ENOBUFS");
- X }
- X bomb("send_lpd_signal:socket:dont_know");
- X }
- X server.sun_family = AF_UNIX;
- X#ifndef lint
- X (void)strcpy((char *)server.sun_path, (char *)"/dev/printer");
- X#endif
- X if ((int)connect(s, (struct sockaddr *)&server, (int)strlen(server.sun_path) + 2) < 0)
- X {
- X bomb("connect");
- X (void) close(s);
- X return(0);
- X }
- X (void) sprintf(buf, "\1%s\n", printer);
- X n = strlen(buf);
- X if (write(s, buf, n) != n)
- X {
- X bomb("write");
- X (void) close(s);
- X return(0);
- X }
- X if (read(s, buf, 1) == 1)
- X {
- X if (buf[0] == '\0')
- X {
- X (void)close(s);
- X return(1);
- X }
- X (void)putchar(buf[0]);
- X }
- X while ((n = read(s, buf, sizeof(buf))) > 0)
- X (void)fwrite(buf, 1, n, stdout);
- X (void)close(s);
- X (void)debug("Signal has been sent to the printer %s.\n");
- X return(0);
- X}
- END_OF_FILE
- if test 9835 -ne `wc -c <'printer.c'`; then
- echo shar: \"'printer.c'\" unpacked with wrong size!
- fi
- # end of 'printer.c'
- fi
- echo shar: End of archive.
- exit 0
- exit 0 # Just in case...
-